package pay.portal;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.annotations.common.util.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import pay.base.BaseCtrl;
import pay.common.ConstantFYJZH;
import pay.common.HqlFilter;
import pay.common.ResultCode;
import pay.enm.WithdrawStatusEnum;
import pay.entity.Payment;
import pay.entity.SysUser;
import pay.entity.Trade;
import pay.portal.web.message.TradeFYReq;
import pay.service.*;
import pay.service.sys.ISysUser;
import pay.utils.ConstantPush;
import pay.utils.MsgTypeConstants;
import pay.utils.SecurityUtils;

/**
 * 提现接口
 *
 * @author jeff
 */
@Controller
@EnableAutoConfiguration
@RequestMapping(value = BaseCtrl.App)
public class WithdrawCtrl extends BaseCtrl {

    @Autowired
    private ISysUser sysUserService;

    @Autowired
    private ITrade tradeService;

    @Value("${server.scheme}")
    private String serverScheme;

    @Value("${fy.goldAccount.pathBaseUrl}")
    private String pathBaseUrl;// 测试环境为/jzh 生产无。

    @Value("${server.url}")
    private String serverUrl;

    @Value("${fy.withdrawLogFilePath}")
    private String logFilePath;

    @Autowired
    private IMessageService messageService;

    @Autowired
    private IPaymentJPA paymentJPA;

    @Autowired
    private IUserCache userCacheService;

    @Autowired
    private IFYResultCode fyResultCodeService;




    @ResponseBody
    @RequestMapping(value = "/withDraw", produces = "application/json;charset=UTF8", method = RequestMethod.POST)
    public void withDraw(HttpServletRequest request,
                         HttpServletResponse response) {

        String responseMsg = "";

        String responseCode = "";
        logger.info("进入富友提现函数");

        // 响应码
        String resp_code = request.getParameter("resp_code");

        // 响应消息
        String resp_desc = request.getParameter("resp_desc");

        // 商户代码,强制
        String mchnt_cd = request.getParameter("mchnt_cd");

        // 流水号， 强制
        String mchnt_txn_ssn = request.getParameter("mchnt_txn_ssn");

        // 交易用户
        String login_id = request.getParameter("login_id");

        // 交易金额,以分为单位 (无小数位)
        String amt = request.getParameter("amt");

        // 签名数据
        String signature = request.getParameter("signature");

        Trade trade = new Trade();
        trade.setAmt(new BigDecimal(amt).divide(new BigDecimal(100)));
        trade.setCts(System.currentTimeMillis());
        trade.setMchnt_txn_ssn(mchnt_txn_ssn);
        trade.setFlowType(ConstantFYJZH.BALANCE_CUT);
        trade.setType(ConstantFYJZH.TRADE_TY_TX);
        trade.setTradeDesc("提现");
        trade.setResp_code(resp_code);
        trade.setResp_desc(resp_desc);
        trade.setLogin_id(login_id);
        if(ConstantFYJZH.FY_REQCODE_SUCC.equals(resp_code)){
            trade.setWithdrawStatus(WithdrawStatusEnum.AUDITING);
        }else {
            trade.setWithdrawStatus(WithdrawStatusEnum.FAIL);
        }

        responseCode = resp_code;

        logger.info(
                "富友提现回调函数, 返回的参数是入：resp_code={}，resp_desc={}， mchnt_cd={}，mchnt_txn_ssn={}，login_id={}， amt={}",
                resp_code, resp_desc, mchnt_cd, mchnt_txn_ssn, login_id, amt);
        // 01判断参数是否为空
        if (StringHelper.isEmpty(resp_code) || StringHelper.isEmpty(mchnt_cd)
                || StringHelper.isEmpty(mchnt_txn_ssn)
                || StringHelper.isEmpty(login_id) || StringHelper.isEmpty(amt)
                || StringHelper.isEmpty(signature)) {
            logger.info("ChongZhiCtrl、Chongzhi 入参有值为空！");

            responseMsg = "传入参数不完整";
            reDirect(response, responseMsg, responseCode, mchnt_txn_ssn);
        }


        // 02 首先判断用户是否存在
        SysUser user = sysUserService.getByPhoneNum(login_id);
        if (user == null) {
            logger.info("用户不存在 手机号={}", login_id);
            responseMsg = "用户不存在！";

            reDirect(response, responseMsg, responseCode, mchnt_txn_ssn);

        } else {
            trade.setUserId(user.getId());
        }

        try {
            tradeService.writeTradeFile(trade, logFilePath);
        } catch (Exception e) {
            logger.error("提现写交易流水文件异常！", e);
        }
        tradeService.save(trade);
        if (resp_code.equalsIgnoreCase("0000") && user != null) {
            logger.info("提现成功用户Id={},手机号={}, 提现结果={}", user.getId(), login_id,
                    resp_code);
            responseMsg = "提现申请已发起，结果请在5分钟后留意账户流水";

            //提现成功，清除用户投资资产缓存
            try{
                userCacheService.removeUserAssetCache(user.getId());
            }catch (Exception e){
                logger.info("提现成功，删除用户投资资产缓存错误 error={}", e);
            }



            List<Payment> paymentList = paymentJPA.findPaymentList(user.getId());

            Payment payment = null;
            for(Payment p: paymentList) {
                String supportCompany = p.getSupportCompany();
                if (supportCompany.substring(0, 1).equals("1")) {
                    payment = p;
                }
            }

            if (payment != null) {
                String msg = String.format("您已申请提现一笔%s元的资金到您的银行卡（%s尾号%s），T+1到账，实际到账时间以银行为主。", trade.getAmt(), payment.getBankName(), payment.getPaymentNo().substring(payment.getPaymentNo().length() - 4));
                this.messageService.sendMsg(String.valueOf(user.getId()), msg, "提现申请", ConstantPush.WITHDRAW, MsgTypeConstants.WITHDRAW);
            }

        } else {
            logger.info("提现不成功 手机号={}, 提现结果={}", login_id, resp_code);
            responseMsg = "提现失败！";
        }

        reDirect(response, responseMsg, responseCode, mchnt_txn_ssn);
    }

    /**
     * 退票回调接口（提现后，进行到银行交易发生失败进行退票操作，提供给富友调用）
     * @param req
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/withdraw/return/notify" , produces = "application/json;charset=UTF8",  method = RequestMethod.POST)
    public String withdrawReturn(TradeFYReq req){
        logger.info("******进入富友退票回调函数！******");

        //商户代码
        String mchnt_cd = req.getMchnt_cd();

        //流水号
        String mchnt_txn_ssn = req.getMchnt_txn_ssn();

        //交易日期
        String mchnt_txn_dt = req.getMchnt_txn_dt();

        //手机号码
        String mobile_no = req.getMobile_no();

        //充值金额
        String amt = req.getAmt();

        //备注
        String remark = req.getRemark();

        //签名数据
        String signature = req.getSignature();
        logger.info("withdrawReturn params=[mchnt_cd={},mchnt_txn_ssn={},mchnt_txn_dt={},mobile_no={},amt={},remark={},signature={}]",
                mchnt_cd,mchnt_txn_ssn,mchnt_cd,mobile_no,amt,remark,signature);


        //检验签名
        String src = amt+ "|"+mchnt_cd + "|"+ mchnt_txn_dt + "|"+ mchnt_txn_ssn+ "|"+mobile_no+"|"+ remark;
        if(!SecurityUtils.verifySign(src,signature)){
            logger.error("withdrawReturn sign error");
            return ResultCode.IREECT_SIGN.name();
        }

        HqlFilter hql = new HqlFilter();
        hql.addEQFilter("type",2);
        hql.addEQFilter("mchnt_txn_ssn",mchnt_txn_ssn);
        hql.addEQFilter("login_id",mobile_no);
        hql.addEQFilter("withdrawStatus",WithdrawStatusEnum.AUDITING);
        List<Trade> list = tradeService.findByFilter(hql);
        if(list == null && list.size() == 0){
            logger.error("withdrawReturn 不存在的提现流水号={}",mchnt_txn_ssn);
        }

        list.stream()
                .forEach(t ->{
                    t.setResp_code("0001");
                    t.setResp_desc("退票");
                    t.setWithdrawStatus(WithdrawStatusEnum.FAIL);
                    tradeService.update(t);
                    String msg = String.format("您申请提现一笔 %s 元的资金提现失败，请重新操作。",t.getAmt());
                    this.messageService.sendMsg(String.valueOf(t.getUserId()), msg, "提现失败", ConstantPush.WITHDRAW, MsgTypeConstants.WITHDRAW);
                 });

        return "SUCCESS";
    }




    // 进行页面跳转
    public void reDirect(HttpServletResponse response, String responseMsg,
                         String responseCode, String mchnt_txn_ssn) {

        String codeMsg = fyResultCodeService.getCodeMsg(responseCode);

        if(codeMsg != null && !"0000".equals(responseCode)){
            responseMsg = codeMsg;
        }

        logger.info("responseMsg = {}", responseMsg);

        try {
            responseMsg = URLEncoder.encode(responseMsg, "utf-8");

            String url = serverScheme + "://" + serverUrl
                    + "/pays/withdrawResult.html?responseMsg=" + responseMsg
                    + "&responseCode=" + responseCode + "&mchnt_txn_ssn=" + mchnt_txn_ssn;
            logger.info("sendRedirect url={}", url);
            response.sendRedirect(url);
        } catch (UnsupportedEncodingException e) {
            logger.error("提现跳转页面异常！", e);
        } catch (IOException e) {
            logger.error("提现跳转页面异常！", e);
        }
        return ;
    }
}
